/**
 * 
 */
package wpmp.security.mgr.service;

import java.sql.Timestamp;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.StandardBasicTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import wcommons.lang.DateUtils;
import wcommons.lang.NumberUtils;
import wcommons.lang.quickbean.Message;
import wpmp.security.mgr.Statics;
import wpmp.security.mgr.base.BaseService;
import wpmp.security.mgr.dao.OrgDao;
import wpmp.security.mgr.dao.UserDao;
import wpmp.security.mgr.entity.Org;

/**
 * @author Wayne.Wang<5waynewang@gmail.com>
 * @since 8:31:50 PM Feb 25, 2013
 */
@Component
@Transactional(rollbackFor = Exception.class)
public class OrgService extends BaseService {

	private static final Logger LOG = LoggerFactory.getLogger(OrgService.class);

	// 需要更新的字段
	private static final String[] UPDATE_PROPERTIES = { "name", "memo" };

	private static final String SQL_EXISTS_PARENT = "EXISTS(SELECT 1 FROM sys_org WHERE parent_id={alias}.id AND id=?)";

	private OrgDao dao;

	private UserDao userDao;

	@Autowired
	public void setDao(OrgDao dao) {
		this.dao = dao;
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public Org get(Long id) {
		final Org entity = dao.get(id);
		if (entity == null) {
			return entity;
		}
		final Org result = new Org();
		BeanUtils.copyProperties(entity, result);
		return result;
	}

	public Org getRootOrg() {
		return get(Statics.ROOT_ID);
	}

	public Org getUngroupedOrg() {
		return get(Statics.UNGROUPED_ID);
	}

	public Org getParent(Long id) {
		return dao.queryForObject(Restrictions.sqlRestriction(SQL_EXISTS_PARENT, id, StandardBasicTypes.LONG));
	}

	/**
	 * 获取子类
	 * 
	 * @param parentId
	 * @return
	 */
	public List<Org> getChildren(Long parentId) {
		return dao.getChildren(parentId);
	}

	/**
	 * 获取子类最大的排序号
	 * 
	 * @param id
	 * @return
	 */
	int getMaxChildOrderNum(Long id) {
		Integer maxOrderNum = (Integer) dao.createCriteria(Restrictions.eq("parentId", id))
				.setProjection(Projections.max("orderNum")).uniqueResult();
		return maxOrderNum == null ? 0 : maxOrderNum.intValue();
	}

	/**
	 * 校验名称是否有效
	 * 
	 * @param entity
	 * @return
	 */
	public Message validateName(Org entity) {
		Criteria criteria = dao.createCriteria(Restrictions.eq("parentId", entity.getParentId()),
				Restrictions.eq("name", entity.getName()));
		if (NumberUtils.gtZero(entity.getId())) {
			criteria.add(Restrictions.ne("id", entity.getId()));
		}
		if (dao.queryForInt(criteria) > 0) {
			return Message.getErrorMessage("同级别下已存在名称[" + entity.getName() + "]");
		}
		return Message.getDefaultMessage();
	}

	/**
	 * 新增组织/单位
	 * 
	 * @param entity
	 * @return
	 */
	public Message insert(Org entity) {
		final Message message = validateName(entity);
		if (message.notpass()) {
			return message;
		}

		final Timestamp currentTime = DateUtils.newTimestamp();

		entity.setOrderNum(getMaxChildOrderNum(entity.getParentId()) + 1);
		entity.setCreateTime(currentTime);
		entity.setCreateUser(entity.getSysLoginName());
		entity.setUpdateTime(currentTime);
		entity.setUpdateUser(entity.getSysLoginName());
		dao.save(entity);

		final Org parent = dao.get(entity.getParentId());
		entity.setLevel(parent.getLevel() + entity.getId() + ".");
		dao.save(entity);

		message.putAttribute("id", entity.getId());
		message.putAttribute("name", entity.getName());
		message.putAttribute("orderNum", entity.getOrderNum());
		return message;
	}

	/**
	 * 更新组织/单位
	 * 
	 * @param entity
	 * @return
	 */
	public Message update(Org entity) {
		final Message message = validateName(entity);
		if (message.notpass()) {
			return message;
		}

		final Org result = dao.get(entity.getId());

		final String name = result.getName();

		wcommons.beanutils.BeanUtils.copyProperties(result, entity, UPDATE_PROPERTIES, false);

		result.setUpdateTime(DateUtils.newTimestamp());
		result.setUpdateUser(entity.getSysLoginName());
		dao.save(result);

		message.putAttribute("id", entity.getId());
		if (!entity.getName().equals(name)) {
			message.putAttribute("name", entity.getName());
		}

		return message;
	}

	/**
	 * 删除组织/单位
	 * 
	 * @param entity
	 * @return
	 */
	public Message delete(Long id) {
		if (!NumberUtils.gtZero(id)) {
			return Message.getErrorMessage("请选择你要删除的记录");
		}

		Org result = dao.get(id);
		if (result == null) {
			return Message.getErrorMessage("未找到 组织/单位[" + id + "]");
		}

		// 重新排序
		dao.decreaseOrderNumWhenGt(result.getParentId(), result.getOrderNum());

		String level = result.getLevel();

		// 删除本级以及下级所有子类
		dao.deleteByLevel(level);

		// 与用户的关系重新绑定 至未分组
		Integer rowNum = userDao.changeToUngroupedOrgByLevel(level);

		if (LOG.isInfoEnabled()) {
			LOG.info("change to ungrouped org by level[{}], affect row number: {}", level, rowNum);
		}

		return Message.getDefaultMessage();
	}

	public Message sort(Org entity) {
		Org result = dao.get(entity.getId());
		// 父类没变
		if (NumberUtils.eq(result.getParentId(), entity.getParentId())) {
			// 5 > 1
			if (entity.getOrderNum() > result.getOrderNum()) {
				dao.decreaseOrderNumWhenBetween(entity.getParentId(), result.getOrderNum(), entity.getOrderNum());
			}
			// 1 < 5
			else if (entity.getOrderNum() < result.getOrderNum()) {
				dao.increaseOrderNumWhenBetween(entity.getParentId(), entity.getOrderNum(), result.getOrderNum());
			}
			result.setOrderNum(entity.getOrderNum());
			dao.save(result);
		}
		// 父类变了
		else {
			// 原父类下的排序变动
			dao.decreaseOrderNumWhenGt(result.getParentId(), result.getOrderNum());

			int maxOrderNum = getMaxChildOrderNum(entity.getParentId());

			if (entity.getOrderNum() == null || entity.getOrderNum() > maxOrderNum) {
				entity.setOrderNum(maxOrderNum + 1);
			}
			if (entity.getOrderNum() <= 0) {
				entity.setOrderNum(1);
			}
			if (entity.getOrderNum() <= maxOrderNum) {
				// 递增排序号，腾出空间
				dao.increaseOrderNumWhenGe(entity.getParentId(), entity.getOrderNum());
			}

			final String level = result.getLevel();

			result.setOrderNum(entity.getOrderNum());

			final Org parent = dao.get(entity.getParentId());

			result.setLevel(parent.getLevel() + result.getId() + ".");
			result.setParentId(entity.getParentId());
			dao.save(result);

			// 更新子类的level
			dao.updateChildLevel(level, result.getLevel());
		}

		return Message.getDefaultMessage();
	}

	/**
	 * 判断子类是否叶子节点
	 * 
	 * @param parentId
	 * @return {id,is_leaf}
	 */
	public SqlRowSet queryChildrenIsLeaf(Long parentId) {
		return dao.queryChildrenIsLeaf(parentId);
	}
}
